package tms.model;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * The class Task represents a task.
 * 
 * @author Rolf Schmidt
 * @version 2.0
 * 
 */
public class Task extends AbstractModelObject implements PropertyChangeListener {

	/**
	 * contains the ID of this task
	 */
	private int id;
	/**
	 * contains the title of this task
	 */
	private String title;
	/**
	 * contains a (short) description of this task
	 */
	private String description;
	/**
	 * contains the duration of this task in hours
	 */
	private int duration;
	/**
	 * contains the description of the deliverable(s) associated with this task
	 */
	private String deliverable;
	/**
	 * contains the deadline of this task
	 */
	private Date deadline;
	/**
	 * contains the name of the person associated with this task
	 */
	private String person;

	/**
	 * default constructor
	 */
	public Task() {
		super();
		this.id = 0;
		this.title = "none";
		this.description = "none";
		this.duration = 1; // as this is the default set in setDuration()
		this.deliverable = "none";
		this.deadline = Calendar.getInstance().getTime();
		this.person = "nobody";
	}

	@Override
	/**
	 * converts the task object to a string.
	 * the string contains the name of each task attribute followed by its value, 
	 * and it starts and ends with a separator.
	 * Also there is one attribute on each line 
	 * 
	 * @return the string representation of this task
	 */
	public String toString() {
		final String H_LINE = "---------------------------------------";
		StringBuffer sb = new StringBuffer(H_LINE);

		sb.append("\nID: " + Integer.toString(id));
		sb.append("\nTitle: " + title);
		sb.append("\nDescription: " + description);
		sb.append("\nDuration: " + new Integer(duration).toString());
		sb.append("\nDeliverable: " + deliverable);
		sb.append("\nDeadline: " + deadline);
		sb.append("\nPerson: " + person);
		sb.append("\n" + H_LINE + "\n");
		return sb.toString();
	}

	@Override
	/**
	 * evaluates whether this task is equal to another task 
	 * two tasks are equal if all of their attributes are equal
	 * 
	 * @param obj an object to use for comparison
	 * @return true if and only if this task is identical to the passed Object
	 */
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Task other = (Task) obj;
		if (deadline == null) {
			if (other.deadline != null)
				return false;
		} else if (!deadline.equals(other.deadline))
			return false;
		if (deliverable == null) {
			if (other.deliverable != null)
				return false;
		} else if (!deliverable.equals(other.deliverable))
			return false;
		if (description == null) {
			if (other.description != null)
				return false;
		} else if (!description.equals(other.description))
			return false;
		if (duration != other.duration)
			return false;
		if (id != other.id)
			return false;
		if (person == null) {
			if (other.person != null)
				return false;
		} else if (!person.equals(other.person))
			return false;
		if (title == null) {
			if (other.title != null)
				return false;
		} else if (!title.equals(other.title))
			return false;
		return true;
	}

	/**
	 * getter of the id of the task
	 * 
	 * @return the id
	 */
	public int getId() {
		return id;
	}

	/**
	 * setter of the id of the task
	 * if the new id is less than zero, then a default value (zero) is assigned to the task id
	 * Also it fires an id change property event
	 *  
	 * @param id
	 *            the id to set
	 */
	public void setId(int id) {
		int oldValue = this.id;
		if (id < 0) {
			this.id = 0;
		} else {
			this.id = id;
		}
		firePropertyChange("id", oldValue, this.id);
	}

	/**
	 * getter of the title of the task
	 * 
	 * @return the title
	 */
	public String getTitle() {
		return title;
	}

	/**
	 * setter of the title of the task
	 * if the new title is null or empty , then a default value (none) is assigned to the task title
	 * Also it fires a title change property event
	 * 
	 * @param title
	 *            the title to set
	 */
	public void setTitle(String title) {
		String oldValue = this.title;
		if (title == null || title.equals("")) {
			this.title = "none";
		} else {
			this.title = title;
		}
		firePropertyChange("title", oldValue, this.title);
	}

	/**
	 * getter of the description of the task
	 * 
	 * @return the description
	 */
	public String getDescription() {
		return description;
	}

	/**
	 * setter of the description of the task
	 * if the new description is null or empty , then a default value (none) is assigned to the task description
	 * Also it fires a description change property event
	 * 
	 * @param description
	 *            the description to set
	 */
	public void setDescription(String description) {
		String oldValue = this.description;
		if (description == null || description.equals("")) {
			this.description = "none";
		} else {
			this.description = description;
		}
		firePropertyChange("description", oldValue, this.description);
	}

	/**
	 * getter of the duration of the task
	 * 
	 * @return the duration
	 */
	public int getDuration() {
		return duration;
	}

	/**
	 * setter of the duration of the task
	 * if the new duration is less than zero , then a default value (1) is assigned to the task duration
	 * Also it fires a duration change property event
	 * 
	 * @param duration
	 *            the duration to set
	 */
	public void setDuration(int duration) {
		int oldValue = this.duration;
		if (duration <= 0) {
			this.duration = 1; // every task takes at least one hour (otherwise
								// it won't show up in the Gantt chart
		} else {
			this.duration = duration;
		}
		firePropertyChange("duration", oldValue, this.duration);
	}

	/**
	 * getter of the deliverable of the task
	 * 
	 * @return the deliverable
	 */
	public String getDeliverable() {
		return deliverable;
	}

	/**
	 * setter of the deliverable of the task
	 * if the new deliverable is null or empty , then a default value (none) is assigned to the task deliverable
	 * Also it fires a deliverable change property event
	 * 
	 * @param deliverable
	 *            the deliverable to set
	 */
	public void setDeliverable(String deliverable) {
		String oldValue = this.deliverable;
		if (deliverable == null || deliverable.equals("")) {
			this.deliverable = "none";
		} else {
			this.deliverable = deliverable;
		}
		firePropertyChange("deliverable", oldValue, this.deliverable);
	}

	/**
	 * getter of the deadline of the task
	 * 
	 * @return the deadline
	 */
	public Date getDeadline() {
		return deadline;
	}

	/**
	 * setter of the deadline of the task
	 * if the new deadline is null , then the old value is kept
	 * Also it fires a deadline change property event
	 * 
	 * @param deadline
	 *            the deadline to set
	 */
	public void setDeadline(Date deadline) {
		Date oldValue = this.deadline;
		if (deadline == null) {
			this.deadline = oldValue;
		} else {
			this.deadline = deadline;
		}
		firePropertyChange("deadline", oldValue, this.deadline);
	}

	/**
	 * getter of the person name assigned to the task
	 * 
	 * @return the person
	 */
	public String getPerson() {
		return person;
	}

	/**
	 * setter of the person name assigned to the task
	 * if the new person name is null or empty , then a default value (nobody) is assigned 
	 * Also it fires a person change property event
	 * 
	 * @param person
	 *            the person to set
	 */
	public void setPerson(String person) {
		String oldValue = this.person;
		if (person == null || person.equals("")) {
			this.person = "nobody";
		} else {
			this.person = person;
		}
		firePropertyChange("person", oldValue, this.person);
	}

	/**
	 * helper method to format a date object as MM/DD/YYYY string 
	 * if the passed date is null, the returned string is empty
	 * 
	 * @param date
	 *            the date to format
	 * @return the formatted date string
	 */
	public String formatDate(Date date) {
		if (date == null) {
			return "";
		}
		String DATE_FORMAT = "MM/dd/yyyy";
		SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);

		return sdf.format(date);
	}

	@Override
	/**
	 * this method gets called whenever there is a property change
	 * 
	 *  @param evt a PropertyChangeEvent object describing the event source and the property that has changed.
	 */
	public void propertyChange(PropertyChangeEvent evt) {
		// TODO Auto-generated method stub
	}

}